import { mapGetters } from 'vuex'
import { Feature, View, Map } from 'ol'
import { ScaleLine, OverviewMap } from 'ol/control'
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer'
import { XYZ as XYZSource, Vector as VectorSource, Cluster } from 'ol/source'
import { WKT } from 'ol/format'
import { Fill, Stroke, Style, Icon, Text, Circle } from 'ol/style'
import { LineString, Point } from 'ol/geom'
import { fromExtent } from 'ol/geom/Polygon'
import markerImg from '@/assets/img/point.png'
import faultImg from '@/assets/img/fault.png'
import { colorData, categoryNode, nodeColor } from '../vis/js/format'
import { getOpacityColor } from '@/utils/common'
import AreaShapeApi from '@/api/system/AreaShapeApi'
import store from '@/store'
const mapConfig = window.__mapConfig__

export default {
  data() {
    return {
      vectorLayer: null,
      vectorMarkLayer: null,
      satelliteLayer: null,
      satelliteMarkLayer: null,
      terrainLayer: null,
      layerList: [],
      setaa: false
    }
  },
  computed: {
    ...mapGetters(['getAreaName', 'regionTree', 'getTheme']),
    textStroke() {
      return this.getTheme === 'dark-theme' ? '#101115' : '#fff'
    }
  },
  methods: {
    // 加载高德底图
    getAmapLayers() {
      const layerList = []
      if (!mapConfig.onlineMap) {
        if (mapConfig.offlineLayer.source) {
          const vectorLayer = this.amapLayer(
            mapConfig.offlineLayer.source,
            mapConfig.offlineLayer.option,
            'vector'
          )
          layerList.push(vectorLayer)
          const darkblueLayer = this.amapLayer(
            mapConfig.offlineLayer.source,
            { visible: false },
            'darkblue'
          )
          layerList.push(darkblueLayer)
        }
      } else {
        if (mapConfig.vectorLayer.source) {
          const vectorLayer = this.amapLayer(
            mapConfig.vectorLayer.source,
            mapConfig.vectorLayer.option,
            'vector'
          )
          layerList.push(vectorLayer)
          const darkblueLayer = this.amapLayer(
            mapConfig.vectorLayer.source,
            { visible: false },
            'darkblue'
          )
          layerList.push(darkblueLayer)
        }
        if (mapConfig.satelliteLayer.source) {
          const satelliteLayer = this.amapLayer(
            mapConfig.satelliteLayer.source,
            mapConfig.satelliteLayer.option,
            'satellite'
          )
          layerList.push(satelliteLayer)
        }

        if (mapConfig.satelliteMarkLayer.source) {
          const satelliteMarkLayer = this.amapLayer(
            mapConfig.satelliteMarkLayer.source,
            mapConfig.satelliteMarkLayer.option,
            'satellite'
          )
          layerList.push(satelliteMarkLayer)
        }
      }
      if (!layerList.length) {
        this.$message.error('请配置地图源信息')
        return
      }
      return layerList
    },
    amapLayer(url, opt = {}, type = 'vector') {
      if (!opt.dataZooms || !opt.dataZooms.length) {
        opt.dataZooms = [1, 18]
      }
      const newLayer = new TileLayer(
        Object.assign(
          {
            source: new XYZSource({
              url: url,
              minZoom: opt.dataZooms[0],
              maxZoom: opt.dataZooms[1],
              tileLoadFunction: (imageTile, src) => {
                if (type !== 'darkblue') {
                  imageTile.getImage().src = src
                  return
                }
                // console.log(imageTile, src)
                // 使用滤镜 将白色修改为深色
                const img = new Image()
                // img.crossOrigin = ''
                // 设置图片不从缓存取，从缓存取可能会出现跨域，导致加载失败
                img.setAttribute('crossOrigin', 'anonymous')
                img.onload = () => {
                  const canvas = document.createElement('canvas')
                  const w = img.width
                  const h = img.height
                  canvas.width = w
                  canvas.height = h
                  const context = canvas.getContext('2d')
                  context.filter =
                    'grayscale(98%) invert(100%) sepia(20%) hue-rotate(180deg) saturate(1600%) brightness(80%) contrast(90%)'
                  context.drawImage(img, 0, 0, w, h, 0, 0, w, h)
                  imageTile.getImage().src = canvas.toDataURL('image/png')
                }
                img.onerror = () => {
                  imageTile.getImage().src = require(type === 'darkblue'
                    ? '@/assets/img/empty_holder_dark.png'
                    : '@/assets/img/empty_holder.png')
                }
                img.src = src
              }
            }),
            renderMode: type === 'darkblue' ? 'vector' : type
          },
          opt
        )
      )
      this.layerList.push({
        layer: newLayer,
        type: type
      })
      return newLayer
    },
    initMap() {
      const option = {
        view: new View({
          projection: 'EPSG:4326',
          center: this.center,
          zoom: this.zoom
        }),
        target: this.mapId,
        controls: [new ScaleLine()],
        layers: []
      }
      // option.layers = this.getAmapLayers()
      this.map = new Map(option)
      // if (mapConfig.isOffline) {
      //   this.offlineLayer = this.creatLayerMap({ zIndex: 2 })
      //   // this.offlineOverviewLayer = this.creatLayerMap({ zIndex: 2 }, null, true)
      //   this.getOfflineData()
      // } else {
      const mapLayers = this.getAmapLayers()
      mapLayers.forEach(i => {
        this.map.addLayer(i)
      })
      this.localThemeType()
      // this.setOverview(this.getAmapLayers(true))
      // }
      this.stationLayer = this.creatLayerMap({ zIndex: 5 })
      this.cableLayer = this.creatLayerMap({ zIndex: 3 })
      this.facilityLayer = this.creatLayerMap({ zIndex: 4 })
      this.facilityLayer.setVisible(false)
      this.clusterLayer = this.creatLayerMap(
        {
          zIndex: 6,
          style: (feature, resolution) => this.clusterStyle(feature, resolution)
        },
        new Cluster({
          source: new VectorSource(),
          distance: 100
        })
      )
      this.clusterLayer.setVisible(false)
      this.mapReady = true
      this.renderMap()
    },
    creatLayerMap(option = {}, source, isOverview = false) {
      source = source || new VectorSource()
      const layer = new VectorLayer({
        source: source,
        ...option
      })
      !isOverview && this.map.addLayer(layer)
      return layer
    },
    // 标点颜色样式
    stationStyle(data, highLight, linkColor) {
      let img = categoryNode(data)
      let color = nodeColor(data)
      if (highLight || linkColor) {
        img = categoryNode(data, linkColor || 'highLight')
        color = linkColor ? colorData[linkColor] : colorData.highLight
      }
      let scale = 0.3
      if (this.showType === 'regionLocate') {
        img = markerImg
        scale = 0.8
      }
      let zIndex = 1
      let offsetY = 28
      if (data.status === 'faultPoint') {
        img = faultImg
        color = colorData.damage
        zIndex = 2
        offsetY = -28
      }
      // 设置标注样式
      const _this = this
      data.label = data.label || ''
      const labelStr = data.label.length > 6 ? data.label.slice(0, 6) + '...' : data.label
      return new Style({
        text: new Text({
          font: 'bold 14px arial',
          text: labelStr,
          fill: new Fill({
            color: color
          }),
          stroke: new Stroke({
            color: _this.textStroke
          }),
          offsetY: offsetY
        }),
        image: new Icon({
          src: img,
          scale: scale
        }),
        zIndex: zIndex
      })
    },
    // 站点单元
    createStation(data, highLight = false, color = null) {
      // 用于充当标注的要素
      const stationFeature = new Feature({
        geometry: new Point(data.location),
        layerType: 'node',
        data: data
      })
      // 添加标注的样式
      stationFeature.setStyle(this.stationStyle(data, highLight, color))
      stationFeature.setId(data.nodeId)
      return stationFeature
    },
    lineStyle(data, highLight = false, linkColor = null, hide) {
      let color = colorData.normal
      if (data.status === 'DAMAGE' && !store.getters.hideAlarmLevel.includes(1)) {
        color = colorData.damage
      }
      let width = 2
      if (highLight || linkColor) {
        color = linkColor ? colorData[linkColor] : color
        width = 6
      }
      if (
        this.layingMethodFilter.enable &&
        !this.layingMethodFilter.cableIds.includes(data.cableId)
      ) {
        color = 'rgba(140, 151, 143, 0.6)'
      }
      // 设置标注样式
      return new Style({
        stroke: new Stroke({
          width: width,
          color: color
        }),
        text: new Text({
          font: 'bold 14px arial',
          text: hide ? '' : highLight ? data.label : '',
          offsetY: -14,
          fill: new Fill({
            color: color
          })
        })
      })
    },
    // 创建连线
    createLineString(data, highLight = false, linkColor = null) {
      // 创建一个 线元素
      const lineFeature = new Feature({
        geometry: new LineString(data.path),
        data: data,
        layerType: 'edge'
      })
      // 添加标注的样式
      lineFeature.setStyle(this.lineStyle(data, highLight, linkColor))
      lineFeature.setId(data.id)
      return lineFeature
    },
    facilityStyle(data, showLabel) {
      // 设置标注样式
      const _this = this
      const labelStr = showLabel ? data.facilityName.length > 6 ? data.facilityName.slice(0, 6) + '...' : data.facilityName : null
      return new Style({
        text: new Text({
          font: 'bold 14px arial',
          text: labelStr,
          fill: new Fill({
            color: colorData.normal
          }),
          stroke: new Stroke({
            color: _this.textStroke
          }),
          offsetY: 28
        }),
        image: new Circle({
          fill: new Fill({
            color: colorData.normal
          }),
          stroke: new Stroke({
            color: colorData.normal,
            width: 1.25
          }),
          radius: 5
        })
      })
    },
    // 设施点
    createFacility(data, showLabel) {
      // 用于充当标注的要素
      const facilityFeature = new Feature({
        geometry: new Point(data.location),
        layerType: 'node',
        data: data
      })
      // 添加标注的样式
      facilityFeature.setStyle(this.facilityStyle(data, showLabel))
      facilityFeature.setId(data.facilityId)
      return facilityFeature
    },
    offlineStyle(areaId) {
      return new Style({
        fill: new Fill({
          color: 'rgba(255, 255, 255, 0.4)'
        }),
        stroke: new Stroke({
          color: '#FF0000',
          width: 1
        }),
        text: new Text({
          font: '12px arial',
          text: this.getAreaName(areaId),
          fill: new Fill({
            color: 'blue'
          })
        })
      })
    },
    clusterStyle(feature, resolution) {
      var size = feature.get('features').length
      return new Style({
        image: new Circle({
          radius: 15,
          stroke: new Stroke({
            color: colorData.topoColor
          }),
          fill: new Fill({
            color: getOpacityColor(colorData.topoColor, 0.5)
          }),
          opacity: 0.5
        }),
        text: new Text({
          font: '14px arial',
          text: size.toString(),
          fill: new Fill({
            color: '#fff'
          })
        })
      })
    },
    setOverview(layers) {
      if (this.showType !== 'home') return
      const overviewMapControl = new OverviewMap({
        className: 'ol-overviewmap ol-custom-overviewmap',
        layers: layers,
        collapsed: false
      })
      !this.setaa && this.map.addControl(overviewMapControl)
    },
    // 获取行政区规划地图数据
    getOfflineData() {
      const format = new WKT()
      const extent = this.map.getView().calculateExtent(this.map.getSize())
      const Rectangle = new Feature({
        geometry: fromExtent(extent)
      })
      const mapExtent = format.writeFeature(Rectangle, {
        dataProjection: 'EPSG:4326',
        featureProjection: 'EPSG:3857'
      })
      AreaShapeApi.spatialQuery({
        extent: mapExtent,
        level: this.level
      }).then(res => {
        if (!res) return
        this.offlineLayer.getSource().clear()
        // this.offlineOverviewLayer.getSource().clear()
        res.forEach(i => {
          const feature = format.readFeature(i.shape, {
            // dataProjection: 'EPSG:4326',
            // featureProjection: 'EPSG:3857'
          })
          feature.setStyle(this.offlineStyle(i.areaId))
          this.offlineLayer.getSource().addFeature(feature)
          // this.offlineOverviewLayer.getSource().addFeature(feature)
        })
        // this.setOverview([this.offlineOverviewLayer])
        this.setaa = true
      }).catch(err => {
        console.log(err)
      })
    }
  }
}
